import {Boundary} from "../map/boundary.mjs";
import {MyArray} from "../utils/array.mjs";

function meshgrid(arr) {
    return arr.map(i => arr.map(j => [i, j]))  //.flat()
}

export class Player {
    #offsets
    #keys = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight']
    #y_keys = this.#keys.slice(-2)

    constructor(x, y, gameMap) {
        this.#offsets = meshgrid([-1, 0, 1])
        this.pos = [x, y]
        this.peekArray = this.getPeekArray(x, y)

        // this.tileArray = tileArray
        this.gameMap = gameMap
        gameMap.initState(this.peekArray)
        this.boundary = new Boundary(gameMap.mapSize)
    }

    setEventListener() {
        let nextPos = this.nextPos.bind(this)
        window.addEventListener('keydown', nextPos)
    }

    nextPos(event) {
        let key = event.key
        if(!this.#keys.includes(key) || this.boundary.on(key))
            return

        let onYDirection = this.#y_keys.includes(key)
        let [k, dx, dy] = [0, 1, 0]
        if (onYDirection) {
            [k, dx, dy] = [1, 0, 1]
            this.peekArray = MyArray.transpose(this.peekArray)
        }

        let push, sign = 1, cutPoints, enteringPoints, leavingPoints
        switch (key) {
            case 'ArrowUp':
            case 'ArrowLeft':
                [sign, dx, dy] = [-1, -dx, -dy]
                cutPoints = this.peekArray[0]
                push = arr => this.peekArray.unshift(arr)
                leavingPoints = this.peekArray.pop()
                break
            case 'ArrowDown':
            case 'ArrowRight':
                cutPoints = this.peekArray.slice(-1)[0]
                push = arr => this.peekArray.push(arr)
                leavingPoints = this.peekArray.shift()
                break
        }

        enteringPoints = cutPoints.map(([x, y]) => [x + dx, y + dy])
        push(enteringPoints)

        this.gameMap.removeState(leavingPoints, 'peek')
        this.gameMap.addState(enteringPoints, 'peek')

        this.gameMap.removeState(this.pos, 'cloaked', 'peek', 'player')
        this.pos[k] += sign
        // this.pos[k]++
        this.gameMap.addState(this.pos, 'player')

        this.boundary.reset(this.pos)

        if (onYDirection)
            this.peekArray = MyArray.transpose(this.peekArray)
    }

    getPeekArray(x, y) {
        return this.#offsets.map(row =>
            row.map(([x_off, y_off]) => [x + x_off, y + y_off]))
    }
}
